﻿using ManYan.Application.WechatUser.Dto;
using ManYan.Domain.DomainService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ManYan.Common;
using ManYan.Common.jwt;
using ManYan.Domain.Model.Entity;
using Microsoft.AspNetCore.Mvc;
using System.Runtime.InteropServices;
using Newtonsoft.Json.Linq;
using Amazon.S3.Model.Internal.MarshallTransformations;

namespace ManYan.Application.WechatUser
{
    public class WechatUserAppService : IWechatUserAppService
    {
        private readonly IWechatUserDomainService _wechatUserDomainService;

        private readonly IBaseAppService<tb_user_refresh_token> _baseAppService;

        public WechatUserAppService(IWechatUserDomainService wechatUserDomainService, IBaseAppService<tb_user_refresh_token> baseAppService)
        {
            _wechatUserDomainService = wechatUserDomainService;
            _baseAppService = baseAppService;
        }
        /// <summary>
        /// 刷新token
        /// </summary>
        /// <param name="access_token"></param>
        /// <param name="refresh_token"></param>
        /// <returns></returns>
        public Res RefreshToken(string access_token, string refresh_token)
        {
            //通过刷新token来获取用户的ID,tb_user_refresh_token
            // var list= _baseAppService.LoadEntityEnumerable(x=>x.Token==refresh_token)
            var res = _baseAppService.WhereLoadEntity(x => x.Token == refresh_token).Data as tb_user_refresh_token;

            if (res?.Valid == true)//表示刷新token有效
            {
                Guid userId = res.UserId;//可以通过UserId来再生成访问token
                if (userId != Guid.Empty)
                {
                    JwtHelper jwtHelper = new JwtHelper();
                    JwtSetting jwtSetting = new JwtSetting();
                    jwtSetting.UserId = userId.ToString();
                    jwtSetting.RoleId = "";
                    jwtSetting.UserNickName = "";
                    access_token = jwtHelper.CreateJwt(jwtSetting);
                    refresh_token = jwtHelper.CreateRefreshToken();//把refresh token写到数据库
                    //删除原来的用户refresh token,用数据库和用redis的一个最基本的区别：如果用redis会不会存在删除refresh_token，不存在，rediskey有失效时间，如果失效，自动清理
                    _baseAppService.DelEntity(x => x.UserId == userId);
                    _baseAppService.AddEntity(new tb_user_refresh_token() { Id = Guid.NewGuid(), Token = refresh_token, UserId = userId, ValidDate = System.DateTime.Now.AddMinutes(40) });

                    return new Res()
                    {
                        Code = 200,
                        Msg = "token刷新成功",
                        Data = new
                        {
                            access_token = access_token,
                            refresh_token = refresh_token

                        }
                    };
                }
                else

                {
                    return new Res() { Code = 401, Msg = "用户不存在" };
                }

            }
            else
            {
                return new Res() { Code = 401, Msg = "刷新token无效或是不存在" };
            }
        }
        public async Task<Res> WechatLoginAsync(WechatUserAddDto dto)
        {
            if (dto.OpenId == null)
            {
                throw new Exception("openid不能为空");
            }
            if (dto.NickName == null)
            {
                throw new Exception("NickName不能为空");
            }
            if (dto.Avatar == null)
            {
                throw new Exception("Avatar不能为空");
            }
            string[] res = await WxLogin(dto.OpenId);
            if (res!=null) {

                var user = _wechatUserDomainService.WechatUserAdd(res[0], dto.NickName, dto.Avatar, String.Empty);

                //  var user=  _wechatUserDomainService.WhereLoadEntity(x=>x.OpenId==dto.OpenId);
                if (user != null)
                {
                    //如果成功，在后续拿到用户的角色，ID等相关数据
                    Common.jwt.JwtHelper jwtHelper = new Common.jwt.JwtHelper();
                    JwtSetting jwtSetting = new JwtSetting();
                    string[] roles = new string[] { "管理员", "总裁" };
                    jwtSetting.RoleId = String.Join(',', roles);
                    jwtSetting.UserId = user.Id.ToString();
                    jwtSetting.RemoteIP = dto.IP;
                    jwtSetting.UserOrgId = "it";
                    jwtSetting.UserNickName = user.NickName;
                    string token = jwtHelper.CreateJwt(jwtSetting);
                    string refresh_token = jwtHelper.CreateRefreshToken();//把refresh token写到数据库
                    _baseAppService.DelEntity(x => x.UserId == user.Id);
                    _baseAppService.AddEntity(new tb_user_refresh_token() { Id = Guid.NewGuid(), Token = refresh_token, UserId = user.Id, ValidDate = System.DateTime.Now.AddMinutes(40) });
                    return new Res()
                    {
                        Code = 200,
                        Msg = "登录成功",
                        Data = new
                        {
                            access_token = token,
                            refresh_token = refresh_token

                        }
                    };
                }
                else
                {
                    return new Res() { Code = 4001, Msg = "用户不存在", Data = null };
                }
            }
            else
            {
                return new Res() { Code = 4001, Msg = "登录失败", Data = null };
            }



        }
        /// <summary>
        /// 获取微信unionid、openid
        /// </summary>
        /// <param name="jscode"></param>
        /// <returns></returns>
        [HttpPost(nameof(WxLogin))]
        public async Task<string[]> WxLogin(string jscode)
        {
            string smallAppId = "wxeb9669089ea9e825"; //你的APPID
            string smallSecretKey = "9d23c5471cf8d5c67c3b8d9cce138eac"; //你的Secret
            //去腾讯服务器换取openid
            var url = $"https://api.weixin.qq.com/sns/jscode2session?appid={smallAppId}&secret={smallSecretKey}&js_code={jscode}&grant_type=authorization_code";
            var resp = await new HttpClient().GetStringAsync(url);
            if (string.IsNullOrEmpty(resp))
            {
                return null;
            }
            else
            {
                var json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(resp);
                //若有多端且共用一个主体，则用unionid
                string unionid = json?.unionid ?? "";
                //若只有一端，则用openid
                string openId = json?.session_key ?? "";
                string sessionKey = json?.openid ?? "";
                return new string[] { openId , unionid , sessionKey };

            }
        }
    }
}
